/**
 * @author: 團長
 * @date: 2013-5-14-下午5:57:39
 */
package net.loyintean.pearlshell.basedb.impl;

import java.sql.SQLException;
import java.util.List;

import org.apache.log4j.Logger;

import net.loyintean.pearlshell.base.model.ILogInfo;
import net.loyintean.pearlshell.base.model.ResultData;
import net.loyintean.pearlshell.base.model.impl.LogInfoFactory;
import net.loyintean.pearlshell.basedb.EditDBService;
import net.loyintean.pearlshell.basedb.ListQueryDBService;
import net.loyintean.pearlshell.basedb.PagedQueryDBService;
import net.loyintean.pearlshell.basedb.QueryDBService;
import net.loyintean.pearlshell.basedb.RemoveDBService;
import net.loyintean.pearlshell.basedb.SaveDBService;
import net.loyintean.pearlshell.basedb.dao.BaseDao;
import net.loyintean.pearlshell.basedb.dao.BasicDao;
import net.loyintean.pearlshell.basedb.dto.BaseDto;
import net.loyintean.pearlshell.basedb.exception.TransactionException;

/** 默认的基础数据库服务实现类
 * <p>
 * 2013年09月18日 团长 增加IBatchDBService接口
 * <p>
 * 2014-8-1 Loy 增加 {@link #editSingleDto(BaseDto)}方法，并且废弃了
 * {@link #editSingleDto(BaseDto)}方法。 v2014-8-1.1.1.0
 * 
 * @author 團長
 * @since 2014-8-1
 * @version 1.1.0 */
public class DBServiceAdapter<T> implements EditDBService<T>,
		ListQueryDBService<T>, PagedQueryDBService<T>, QueryDBService<T>,
		RemoveDBService<T>, SaveDBService<T> {

	/** 日志记录器
	 * 
	 * @author 團長
	 * @since 2013-5-15 */
	protected final Logger logger = Logger.getLogger(this.getClass());

	/** 数据库接口
	 * 
	 * @author 團長
	 * @since 2013-5-14 */
	protected BasicDao<T> dao;

	/** sql语句 */
	protected String sqlSaveSingleDto, sqlEditSingleDto, sqlQueryDtoList,
			sqlQueryPagedList, sqlQueryTotalCount, sqlRemoveSingleDto,
			sqlQuerySingleDto;

	/** only when the value returned from
	 * {@link BaseDao#insertSingleDto(BaseDto)} is greater then zero, this
	 * method will return an ResultData with status of SUCCESS.<br>
	 * it might cause error in iBatis/myBatis with BATCH executor.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.ISaveDBService
	 *      #saveSingleDto(net.loyintean.pearlshell.basedb.dto.BaseDto) */
	@Override
	public ResultData<T> saveSingleDto(T dto) throws TransactionException {
		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		ResultData<T> id = ResultData.INIT();

		try {
			int result = dao.insertSingleDto(dto, sqlSaveSingleDto);

			if (result > 0) {
				id.success(dto);
			} else {
				id.fail("can't insert correctly with " + dto
						+ " ! rows/id returned is " + result + "!");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			id.fail(e.getMessage());

		}

		logger.info(logInfo.end("@id=" + id));
		return id;
	}

	/** only when the value returned from
	 * {@link BaseDao#deleteSingleDto(BaseDto)} is greater then zero, this
	 * method will return an ResultData with status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IRemoveDBService
	 *      #removeSingleDto(net.loyintean.pearlshell.basedb.dto.BaseDto) */
	@Override
	public ResultData<Integer> removeSingleDto(T dto)
			throws TransactionException {
		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		ResultData<Integer> result = ResultData.INIT();

		try {
			int rows = dao.deleteSingleDto(dto, sqlRemoveSingleDto);

			if (rows > 0) {
				result.success(rows);
			} else {
				result.fail("nothing removed from db with " + dto + " !", 0);
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			result.fail(e.getMessage());
		}

		logger.info(logInfo.end("@rows=" + result));
		return result;

	}

	/** only when the value returned from
	 * {@link BaseDao#selectSingleDto(BaseDto)} is not null, this method will
	 * return an ResultData with status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IQueryDBService
	 *      #querySingleDto(net.loyintean.pearlshell.basedb.dto.BaseDto) */
	@Override
	public ResultData<T> querySingleDto(T dto) throws TransactionException {

		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		ResultData<T> result = ResultData.INIT();

		try {
			T dbRow = dao.selectSingleDto(dto, sqlQuerySingleDto);

			if (dbRow != null) {
				result.success(dbRow);
			} else {
				result.fail("nothing can be find out from db with " + dto
						+ " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			result.fail(e.getMessage());
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/** only when the value returned from {@link BaseDao#selectDtoList(BaseDto)}
	 * is not null and not empty, this method will return an ResultData with
	 * status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IListQueryDBService
	 *      #queryDtoList(net.loyintean.pearlshell.basedb.dto.BaseDto) */
	@Override
	public ResultData<List<T>> queryDtoList(T dto) throws TransactionException {

		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		ResultData<List<T>> result = ResultData.INIT();

		try {
			List<T> list = dao.selectDtoList(dto, sqlQueryDtoList);

			if (list != null && !list.isEmpty()) {
				result.success(list);
			} else {
				result.fail("no list can be find out from db with " + dto
						+ " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			result.fail(e.getMessage());
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/** only when the value returned from
	 * {@link BaseDao#selectPagedList(BaseDto)} is not null and not empty, this
	 * method will return an ResultData with status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IPagedQueryDBService
	 *      #queryPagedList(net.loyintean.pearlshell.basedb.dto.BaseDto) */
	@Override
	public ResultData<List<T>> queryPagedList(T dto)
			throws TransactionException {

		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		ResultData<List<T>> result = ResultData.INIT();

		try {
			List<T> list = dao.selectPagedList(dto, sqlQueryPagedList);

			if (list != null && !list.isEmpty()) {
				result.success(list);
			} else {
				result.fail("no paged list can be find out from db with " + dto
						+ " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			result.fail(e.getMessage());
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/** only when the value returned from
	 * {@link BaseDao#selectTotalCount(BaseDto)} is not less then zero, this
	 * method will return an ResultData with status of SUCCESS.
	 * 
	 * @author Loy
	 * @since 2014-9-10
	 * @see net.loyintean.pearlshell.basedb.IPagedQueryDBService
	 *      #queryTotalCount(net.loyintean.pearlshell.basedb.dto.BaseDto) */
	@Override
	public ResultData<Integer> queryTotalCount(T dto)
			throws TransactionException {

		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		ResultData<Integer> result = ResultData.INIT();

		try {
			int count = dao.selectTotalCount(dto, sqlQueryTotalCount);

			if (count >= 0) {
				result.success(count);
			} else {
				result.fail("an error number returned by dao with " + dto
						+ ", the number is " + count + " !");
			}

		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			result.fail(e.getMessage());
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/** call the dao.updateSingleDto(dto). This method has nothing todo with
	 * {@link #editSingleDto(BaseDto)}
	 * 
	 * @author Loy
	 * @since 2014-8-1
	 * @see net.loyintean.pearlshell.basedb.IEditDBService
	 *      #editSingleDto(net.loyintean.pearlshell.basedb.dto.BaseDto) */
	@Override
	public ResultData<Integer> editSingleDto(T dto) throws TransactionException {
		assert dto != null;

		ILogInfo logInfo = LogInfoFactory.BUILD("@dto=" + dto);

		logger.info(logInfo.start());

		ResultData<Integer> result = ResultData.INIT();

		try {
			result.success(dao.updateSingleDto(dto, sqlEditSingleDto));
		} catch (SQLException e) {
			logger.error(logInfo.error(e));
			result.fail(e.getMessage());
		}

		logger.info(logInfo.end("@result=" + result));
		return result;

	}

	/** @param dao
	 *            the dao to set */
	public void setDao(BasicDao<T> dao) {
		this.dao = dao;
	}

	/** @param sqlSaveSignleDto
	 *            the sqlSaveSignleDto to set */
	public void setSqlSaveSignleDto(String sqlSaveSignleDto) {
		this.sqlSaveSingleDto = sqlSaveSignleDto;
	}

	/** @param sqlEditSingleDto
	 *            the sqlEditSingleDto to set */
	public void setSqlEditSingleDto(String sqlEditSingleDto) {
		this.sqlEditSingleDto = sqlEditSingleDto;
	}

	/** @param sqlQueryDtoList
	 *            the sqlQueryDtoList to set */
	public void setSqlQueryDtoList(String sqlQueryDtoList) {
		this.sqlQueryDtoList = sqlQueryDtoList;
	}

	/** @param sqlQueryPagedList
	 *            the sqlQueryPagedList to set */
	public void setSqlQueryPagedList(String sqlQueryPagedList) {
		this.sqlQueryPagedList = sqlQueryPagedList;
	}

	/** @param sqlQueryTotalCount
	 *            the sqlQueryTotalCount to set */
	public void setSqlQueryTotalCount(String sqlQueryTotalCount) {
		this.sqlQueryTotalCount = sqlQueryTotalCount;
	}

	/** @param sqlRemoveSingleDto
	 *            the sqlRemoveSingleDto to set */
	public void setSqlRemoveSingleDto(String sqlRemoveSingleDto) {
		this.sqlRemoveSingleDto = sqlRemoveSingleDto;
	}

	/** @param sqlQuerySingleDto
	 *            the sqlQuerySingleDto to set */
	public void setSqlQuerySingleDto(String sqlQuerySingleDto) {
		this.sqlQuerySingleDto = sqlQuerySingleDto;
	}

}
